<?php
/**
 * 操作数据库类
 * 
 * Copyright (c) 2014~2019 https://desion.net All rights reserved.
 * Author: 阿林 QQ:120867629 <linhong00@gmail.com>
 */
declare (strict_types = 1);
namespace dsphp;
use dsphp\model\Where;

abstract class Model
{
    use Where;

    protected $app;
    protected $db;
    protected $config;
    // 主键
    protected $tablePk = 'id';
    // 表名
    protected $tableName = '';
    // 表前缀 
    protected $tablePrefix = '';
    // 表后缀
    protected $tableSuffix = '';
    // 数据库链接
    protected $connection = 'default';
    // 数据库链
    protected $linkId = true;

    const PAGE_LIMIT = 20;


    /**
     * 构造函数
     *
     * @param App $app
     * @param string $suffix  表后缀
     */ 
    public function __construct(App $app, $suffix = null)
    {
        $this->app = $app;

        if (is_string($suffix)) {
            // $this->tableSuffix = $suffix;
            $this->setTableSuffix($suffix);
        }

        $this->config = $this->app->getConfig('db');

        if ($linkId === true) {
            $this->db($this->connection);
        }

        $this->_initOptions();
    }

    /**
     * 组合最后表明
     *
     * @param  string $suffix
     * @return void
     */
    public function getTableName($suffix = '')
    {
        if (empty($suffix)) {
            $suffix = $this->tableSuffix;
        }

        return $this->tablePrefix . $this->tableName . $suffix;
    }

    /**
     * 设置表后缀
     *
     * @param  string $suffix 后缀
     * @return this
     */
    public function setTableSuffix(string $suffix)
    {
        $this->tableSuffix = $suffix;
        return $this;
    }

    /**
     * 连接数据库
     *
     * @param string  $name    数据库标识
     * @param array   $config  链接参数
     * @param boolean $force   是否重新链接
     */
    public function db(string $name = '', array $config = [], bool $force = false)
    {
        if (empty($name)) {
            $name = $this->connection;
        }

        if (empty($config)) {
            $config = $this->config;
            
            if (! isset($config[$name])) {
                throw new \Exception(500, 'db invalid:' . $name);
            }

            $config = $config[$name];
        }

        $this->db     = $this->app->make('db');
        $this->linkId = $this->db->connect($name, $config, $force);

        return $this->linkId;
    }

    /**
     * 读取列表
     *
     * @return array
     */
    public function dataList()
    {
        return $this->_doDb('select');
    }
    // 全部数据
    public function dataAllList()
    {
        $this->page(1, 0);
        return $this->dataList();
    }
    // 单条
    public function dataOne()
    {
        $this->page(1,1);
        $list = $this->dataList();
        return $list[0] ?? false;
    }

    /**
     * 更新数据
     *
     * @return void
     */
    public function dataUpdate(array $data = [])
    {
        if (empty($this->_options['where'])) {
            return false;
        }

        if ($data) {
            $this->data($data, true);
        }

        return $this->_doDb('update');
    }

    /**
     * 删除数据
     *
     * @return void
     */
    public function dataDelete()
    {
        if (empty($this->_options['where'])) {
            return false;
        }

        return $this->_doDb('delete');
    }

    /**
     * 插入数据
     *
     * @param array $data  插入数据
     * @return void
     */
    public function dataInsert(array $data = [])
    {
        if ($data) {
            $this->data($data, true);
        }

        return $this->_doDb('insert');
    }

    /**
     * 向数据库执行
     *
     * @param string $do    操作类型
     * @param array  $data  插入数据
     * @return void
     */
    private function _doDb(string $do)
    {
        // 非法操作
        if (! in_array($do, ['insert', 'insertAll', 'delete', 'update', 'select'])) {
            return null;
        }
        // 是否返回sql
        $isSql = $this->_returnSql ? true : false;
        // 初始化
        $this->_initConnect();
        // 执行
        $result = $this->linkId->$do($isSql);
        // 还原
        $this->_initOptions();

        return $result;
    }

    /**
     * 判断是否了链接，如果没有则链接
     *
     * @param string $name 数据库标识
     */
    private function _initConnect($name = '')
    {
        $status = $this->linkId ?? false;
        if (empty($status) || $this->linkId === true) {
            $name = $name ?: $this->dbName;
            $this->db($name);
        }

        $this->_options['table'] = $this->getTableName();
        $this->_options['pk']    = $this->tablePk;
        $this->linkId->setOptions($this->_options);
    }
}

